/**
 */

let avoidRoom = ["W17N20","W16N20","W15N20"].reduce((a,b)=>{a[b]= 1;return a} ,{});

let MIN_POWER = 3000 // 少于这个量的不去挖
let MIN_DECAY = 4600 // 第一次看到的 消失时间 少于这个量的不去挖

// 600/tick 伤害 *（150生爬+(2组 +1）) = 450 ，移动时间最高为300 ，750 * 600 = 450000
let CARRY_WAIT_HITS = 450000 // 生命值少于这么多的时候去运输562500


Creep.prototype.registerAttackerPB=function () {
    let headTask = this.headTask();
    let flag = Game.flags[headTask.flagName];
    if(flag){
        flag.memory.attacker = flag.memory.attacker || []
        if(!flag.memory.attacker.contains(this.id)){
            flag.memory.attacker.push(this.id)
        }
    }
}

Creep.prototype.registerHealerPB=function () {
    let headTask = this.headTask();
    let flag = Game.flags[headTask.flagName];
    if(flag){

        this.memory.concated = true
        let pathTime = 1500 - this.ticksToLive;
        if(flag && (!flag.memory.pathTime||flag.memory.pathTime>pathTime)) {
            flag.memory.pathTime = pathTime
        }


        flag.memory.healer = flag.memory.healer || []
        if(!flag.memory.healer.contains(this.id)){
            flag.memory.healer.push(this.id)
        }
    }
}

Creep.prototype.registerCarrierPB=function () {
    let headTask = this.headTask();
    let flag = Game.flags[headTask.flagName];
    if(flag){
        flag.memory.carrier = flag.memory.carrier || []
        if(!flag.memory.carrier.contains(this.id)){
            flag.memory.carrier.push(this.id)
        }
    }
}

Creep.prototype.AttackerPB=function () {
    let task= this.headTask();
    // this.suicide()
    if(task.roomName!=this.room.name){
        this.goTo(task);
    }else{
        let powerBank=Game.getObjectById(task["id"]);
        if(!powerBank){
            this.memory.dontPullMe = false;
            this.popTask();
            this.addTask([UtilsTask.taskData("recycleCreep")])
            this.execLastTask();
            return;
        }
        if(!this.pos.isNearTo(powerBank)){
            this.moveTo(powerBank)
        }
        if(this.hits==this.hitsMax){
            this.attack(powerBank)
        }
    }
};


Creep.prototype.HealerPB=function () {
    let task= this.headTask();
    if(task.roomName!=this.room.name){
        this.goTo(task);
    }else{
        let flag = Game.flags[task.flagName];
        if(!flag){
            this.memory.dontPullMe = false;
            this.popTask();
            this.addTask([UtilsTask.taskData("recycleCreep")])
            this.execLastTask();
            return;
        }
        let attacker = flag.memory.attacker = flag.memory.attacker || []
        attacker = attacker.map(e=>Game.getObjectById(e)).head()
        if(attacker){
            if(!this.pos.isNearTo(attacker))this.moveTo(attacker);
            else this.heal(attacker)
        }
    }
    if(this.hitsMax!=this.hits)this.heal(this);
};

Creep.prototype.carrierPB=function () {
    let task= this.headTask();
    if(task.roomName!=this.room.name){
        this.goTo(task);
    }else{
        if(this.storeUsed()>0){
            this.popTask();
            this.addTask([UtilsTask.taskData("recycleCreep")])
            this.addTask([UtilsTask.task(this.mainRoom().storage,"fillAllTask","registerCarrierPB")])
            this.execLastTask();
            return;
        }
        let ruin = this.room.find(FIND_RUINS).filter(e=>e.store[RESOURCE_POWER]>0).head();
        let power = this.room.find(FIND_DROPPED_RESOURCES)
            .filter(e=>e.resourceType==RESOURCE_POWER)
            .sort((a,b)=>b.amount-a.amount).head();
        if(ruin){
          this.moveTo(ruin);
          this.withdraw(ruin,RESOURCE_POWER)
        } else if(power){
            this.moveTo(power);
            this.pickup(power);
        }else{
            let flag = Game.flags[task.flagName];
            if(flag){
                // let attacker = flag.memory.attacker = flag.memory.attacker || []
                // attacker = attacker.map(e=>Game.getObjectById(e)).head()

                // if(!attacker)
                let attacker = Game.getObjectById(flag.memory.id)

                if(!attacker){

                }else if(!this.pos.inRangeTo(attacker,4)){
                    this.moveTo(attacker)
                }else{
                    this.memory.dontPullMe = true;
                }
            }
        }

    }
};


let pro = {

    createOrUpdatePowerBankMission:function(targetRoomName, powerBankData){
        if(avoidRoom[targetRoomName])return;
        let spawnRoomName = StationObserver.getClosedMyRoomName(targetRoomName);
        let flagName = "powerBank_"+spawnRoomName+"_"+powerBankData.x+"_"+powerBankData.y;
        if(!Memory.flags[flagName])Memory.flags[flagName] = {}
        let flagMemory = Memory.flags[flagName];
        powerBankData.flagName = flagName;
        powerBankData.roomName = targetRoomName;
        for(let k in powerBankData){
            flagMemory[k] = powerBankData[k] ;
        }
        if(!spawnRoomName||powerBankData.power<=MIN_POWER||powerBankData.disappearTime-Game.time<=MIN_DECAY)return;
        if(!Game.flags[flagName]){
            (new RoomPosition(powerBankData.x,powerBankData.y,powerBankData.roomName)).createFlag(flagName)
        }
    },
    trySpawnPBAttack:function (room,memory,isBoostDamage){
        let body = ManagerCreeps.calcBodyPart({ [MOVE]: 10 ,[ATTACK]: 10}).concat(ManagerCreeps.calcBodyPart({ [ATTACK]: 10,[MOVE]: 10}))
        let tasks =[UtilsTask.taskData("AttackerPB","registerAttackerPB",memory)]
        if(isBoostDamage){
            body = ManagerCreeps.calcBodyPart({ [TOUGH]: 2,[MOVE]: 2 }).concat(body);
            tasks.push(UtilsTask.taskData("boostCreepBodyPart","registerBoostCreep",{data: {[BOOST_RES["damage"][1]]:30*2}} ));
        }
        StationHive.trySpawn(room,room.name,body,"PBAttack",tasks)
    },
    trySpawnPBHeal:function (room,memory,isBoostDamage){
        let partCnt = isBoostDamage?13:25
        let body = ManagerCreeps.calcBodyPart({ [MOVE]: partCnt,[HEAL]:  partCnt})
        StationHive.trySpawn(room,room.name,body,"PBHeal",
            [UtilsTask.taskData("HealerPB","registerHealerPB",memory)]
        )
    },
    trySpawnPBCarrier:function (room,memory,isBoostDamage){
        let body = ManagerCreeps.calcBodyPart({ [CARRY]:  33, [MOVE]: 17})
        StationHive.trySpawn(room,room.name,body,"PBCarrier",
            [UtilsTask.taskData("carrierPB","registerCarrierPB",memory)]
        )
    },
    exec:function (room) {
        if((Game.time+room.hashCode()) % 3 != 0) return;
        room.flags("powerBank").forEach(flag=>{
            // log(flag.memory)
            if(flag.memory.disappearTime-Game.time<0||flag.memory.power<MIN_POWER)flag.remove()
            // HelperVisual.mapShowText(flag,flag.name)
            // if(room.name!="W1N4")return;
            let isBoostDamage = 1==StationLab.boostAbleLevel(room,"damage",3,1,1)
            // log(room.name,flag.name,isBoostDamage,flag.memory.disappearTime-Game.time,flag.memory.disappearTime,Game.time)
            flag.memory.attacker = flag.memory.attacker?flag.memory.attacker.filter(id=>Game.getObjectById(id)) : []
            flag.memory.healer = flag.memory.healer?flag.memory.healer.filter(id=>Game.getObjectById(id)) : []
            flag.memory.carrier = flag.memory.carrier?flag.memory.carrier.filter(id=>Game.getObjectById(id)) : []

            if(flag.memory.attacker.map(id=>Game.getObjectById(id)).filter(e=>e.spawning||(e.ticksToLive>(flag.memory.pathTime||0)+150)).length<1){
                pro.trySpawnPBAttack(room,flag.memory,isBoostDamage)
            }
            else if(flag.memory.healer.map(id=>Game.getObjectById(id)).filter(e=>e.spawning||(e.ticksToLive>(flag.memory.pathTime||0)+150)).length<1){
                pro.trySpawnPBHeal(room,flag.memory,isBoostDamage)
            }

            let powerBank = Game.getObjectById(flag.memory.id);
            if(powerBank&&powerBank.hits<CARRY_WAIT_HITS){
                flag.memory.needCarry = 1;
            }

            if(Game.rooms[flag.pos.roomName]){
                if(!powerBank)flag.remove();
            }

            if(flag.memory.needCarry){
                let carrierCnt = Math.ceil(flag.memory.power/1650)
                if(flag.memory.carrier.length<carrierCnt){
                    pro.trySpawnPBCarrier(room,flag.memory,isBoostDamage)
                }
            }
        })
    }

}


global.StrategyPowerBank=pro;